home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / gfa / ymodem / ymodem.lst
Encoding:
File List  |  1992-11-21  |  8.5 KB  |  329 lines

  1. '
  2. '  Xmdoem/Ymodem CRC/CHK Batch Recieve algorithm
  3. '
  4. ' written by Dave Lockwood
  5. '
  6. ' It didn't work last time I tested it, and I don't know why...I haven't
  7. ' taken the time to thoroughly de-bug it, but here it is.  If you manage to
  8. ' make the thing work (especially if you can make it support Ymodem Batch),
  9. ' PLEASE upload it, and let me know what you did...At the very least, there
  10. ' are a few usefull routines here for other programs.
  11. ' In its present state, If it worked, it would support Xmodem w/checksum,
  12. ' Xmodem CRC, Ymodem w/checksum, and Ymodem CRC.
  13. ' My goal in this routine was to support the complete Christenson (sp?)
  14. ' Xmodem standard as defined in his latest papers on the subject.
  15. '
  16. ' *** Global definitions and declarations (place at beginning of code)
  17. '
  18. Nul%=0      ! block 0 filler byte
  19. Soh%=1      ! Start Of Header  (Xmodem -  128 byte blocks)
  20. Stx%=2      ! Start Of Header  (Ymodem - 1024 byte blocks)
  21. Eot%=4      ! End Of Transfer
  22. Ack%=6      ! ACKnolege block
  23. Nak%=21     ! Not AcKnolege block (block error)
  24. Can%=24     ! shitCAN transfer (send two of these to abort Ymodem)
  25. Eof%=26     ! End Of File (CP/M)
  26. C%=43       ! "C"
  27. Rs232%=1    ! RS-232 device number for Out statement
  28. Timeout%=-1 ! timeout value for Inchar routine
  29. '
  30. Ymbuf$=String$(1024,Eof%)   ! block buffer
  31. Block0$=String$(128,Nul%)   ! block 0 (batch filename) buffer
  32. '
  33. ' ****************************** Parity **************************************
  34. ' calculates parity of a byte
  35. ' used for Procedure Calcrc below
  36. ' parameter A% is the byte for which parity is needed
  37. ' returns Parity% (0=even parity/1=odd parity)
  38. ' example:
  39. ' @Parity(Byte%)
  40. ' If Odd(Parity%)
  41. '   ...
  42. Procedure Parity(A%)
  43.   Local Result%,Count%,Q%
  44.   Result%=0
  45.   Count%=8
  46.   While Count%<>0
  47.     Count%=Count%-1
  48.     Q%=A% And 1
  49.     If Q%<>0
  50.       Result%=Result%+1
  51.     Endif
  52.     A%=A%/2
  53.   Wend
  54.   If Odd(Result%)
  55.     Parity%=1
  56.   Else
  57.     Parity%=0
  58.   Endif
  59. Return
  60. ' ******************************** CalCrc ************************************
  61. ' calculates CRC-16 for a single byte at a time
  62. ' parameter Inbyte% is the byte to add to the CRC
  63. ' It updates two global variables Crclo% and Crchi%
  64. ' being the low order and high order 8 bits of the CRC respectively
  65. ' call this routine for each byte in buffer for which CRC is required
  66. ' Crclo% and Crchi% should be set to 0 before calling this routine
  67. ' for the first byte in the buffer.
  68. ' Translated from Z80 assembly language by Paul Krasno & Dave Lockwood
  69. Procedure Calcrc(Inbyte%)
  70.   Local A1%,A2%,A3%,A4%,A%,H%,L%
  71.   H%=0
  72.   L%=0
  73.   A1%=Crchi% Xor Inbyte%
  74.   @Parity(A1%)
  75.   If Odd(Parity%)
  76.     H%=3
  77.     L%=&H80
  78.   Endif
  79.   Crcto2:
  80.   A2%=(2*A1%) Mod 256
  81.   A%=A1% And &H80
  82.   If A%<>0
  83.     L%=L% Xor 2
  84.   Endif
  85.   Crcto3:
  86.   A3%=A2% Xor A1%
  87.   A4%=(2*A3%) Mod 256
  88.   A%=A3% And &H80
  89.   If A%<>0
  90.     L%=L% Xor 1
  91.   Endif
  92.   Crcto4:
  93.   Crchi%=Crclo% Xor L%
  94.   Crclo%=A4% Xor H%
  95. Return
  96. ' ********************************** Inchar **********************************
  97. ' waits for a certain amount of time for input
  98. ' from the RS232 port.
  99. ' parameter Time% is the time in seconds to wait
  100. ' returns Char% containing the input or -1 if timeout occurs
  101. Procedure Inchar(Time%)
  102.   Local Tm%
  103.   Tm%=Timer+Time%*200
  104.   While Timer<>Tm% And Inp?(Rs232%)=False
  105.   Wend
  106.   If Inp?(Rs232%)=True
  107.     Char%=Inp?(Rs232%)
  108.   Else
  109.     Char%=Timeout%
  110.   Endif
  111. Return
  112. ' ********************************** Purge ***********************************
  113. ' clears RS232 input buffer
  114. ' no parameters/no return
  115. Procedure Purge
  116.   Char%=1
  117.   While Char%<>Timeout%
  118.     @Inchar(1)
  119.   Wend
  120. Return
  121. ' ****************************** Ymodem_recieve ******************************
  122. '
  123. ' Ymodem recieve routine
  124. ' Parameter Path$ is the filename of the input file
  125. ' returns nothing
  126. ' doesn't support Ymodem Batch....yet
  127. '
  128. Procedure Ymodem_recieve(Path$)
  129.   Local Batch!,Crc!,Icrclo%,Icrchi%,Block%,Bsize%,Fsize%,I%,File$
  130.   Local Iblk%,Iblkcom%,Ercnt%,S%,Cksum%,Icksum%
  131.   Crc!=True
  132.   Batch!=False
  133.   Bsize%=1024
  134.   Block%=1
  135.   Ercnt%=1
  136.   If Path$=""
  137.     Path$="A:\YMODFILE.DAT"
  138.   Endif
  139.   If Right$(Path$,1)<>"\"
  140.     For I%=Len(Path$) To 1 Step -1
  141.       Exit If Mid$(Path$,I%,1)="\"
  142.     Next I%
  143.     File$=Right$(Path$,Len(Path$)-I%)
  144.     Path$=Left$(Path$,I%)
  145.   Else
  146.     File$="YMODFILE.DAT"
  147.   Endif
  148.   If File$="batch"
  149.     File$=""
  150.     Batch!=True
  151.   Endif
  152.   '
  153.   ' open file here...will be moved when I support batch
  154.   ' for batch, a block 0 handling routine must be added
  155.   ' to get each filename to be downloaded
  156.   '
  157.   Open "O",#1,Path$+File$
  158.   '
  159.   Nxtfile:
  160.   Crc!=True
  161.   Bsize%=1024
  162.   Block%=1
  163.   Out 1,C%            ! Send a "C" to find out if the sender supports CRC
  164.   Sttran:
  165.   @Inchar(3)
  166.   If Char%=Timeout%   ! timeout here means the sender doesn't support CRC
  167.     Crc!=False
  168.     Goto Booboo
  169.   Endif
  170.   Goto Gotsoh
  171.   '
  172.   Startblock:
  173.   '
  174.   Badblock!=False
  175.   @Inchar(1)                              ! get block number
  176.   If Char%=Timeout%
  177.     Print "Timeout getting block number"
  178.     Badblock!=True
  179.     Goto Booboo
  180.   Endif
  181.   Iblk%=Char%
  182.   '
  183.   @Inchar(1)                              ! get block number compliment
  184.   If Char%=Timeout%
  185.     Print "Timeout getting block number compliment"
  186.     Badblock!=True
  187.     Goto Booboo
  188.   Endif
  189.   Iblkcom%=Char%
  190.   '
  191.   Gotblknum:
  192.   '
  193.   If Iblk%=(255-Iblkcom%) And Iblk%=0 And Block%=1 ! Block 0 for batch
  194.     ' Batch!=True
  195.     ' @Handle_block0
  196.     Print "Sender wants batch, and I can't do it!!! (I give up)"
  197.     Out Rs232%,Can%
  198.     Out Rs232%,Can%
  199.     Goto Ymrrtn
  200.   Endif
  201.   '
  202.   If Iblk%<>(Block% And 255) Or Iblkcom%<>(255-(Block% And 255))
  203.     Print "Bad block number ";Iblk%,255-Iblkcom%
  204.     Badblock!=True
  205.     Goto Booboo
  206.   Endif
  207.   '
  208.   Print "Getting block ";Block%;" try number ";Ercnt%
  209.   Badblock!=False
  210.   Crclo%=0
  211.   Crchi%=0
  212.   '
  213.   For I%=1 To Bsize%                      ! get the "meat" of the block
  214.     @Inchar(1)
  215.     If Char%=Timeout%
  216.       Print "Timeout during data block"
  217.       Badblock!=True
  218.     Endif
  219.     Exit If Badblock!=True
  220.     Mid$(Ymbuf$,I%,1)=Chr$(Char%)         ! store each byte in buffer
  221.     If Crc!=True
  222.       @Calcrc(Char%)                      ! calculate CRC
  223.     Else
  224.       Cksum%=Cksum%+Char%                 ! add to sum
  225.     Endif
  226.   Next I%
  227.   '
  228.   If Badblock!=True
  229.     Goto Booboo
  230.   Endif
  231.   '
  232.   @Inchar(1)                              ! get CRC hi byte
  233.   If Char%=Timeout%
  234.     Print "Timeout getting CRC lo byte"
  235.     Badblock!=True
  236.     Goto Booboo
  237.   Endif
  238.   '
  239.   If Crc!=False                           ! if not in CRC mode,
  240.     Icksum%=Char%                         ! that's our checksum
  241.     Goto Check_sum
  242.   Endif
  243.   '
  244.   Icrchi%=Char%
  245.   @Inchar(1)                              ! get CRC lo byte
  246.   If Char%=Timeout%
  247.     Print "Timeout getting CRC hi byte"
  248.     Badblock!=True
  249.     Goto Booboo
  250.   Endif
  251.   Icrclo%=Char%
  252.   '
  253.   If Icrclo%<>Crclo% Or Icrchi%<>Crchi%   ! compare CRC's
  254.     Print "CRC mismatch - mine:";Crchi%*256+Crclo%;", his:";Icrchi%*256+Icrclo%
  255.     Badblock!=True
  256.     Goto Booboo
  257.   Endif
  258.   '
  259.   Block_ok:
  260.   '
  261.   Out 1,Ack%                              ! send ACK
  262.   '
  263.   Awaitsoh:
  264.   '
  265.   @Inchar(10)                             ! wait for SOH or STX
  266.   '
  267.   Gotsoh:
  268.   '
  269.   If Char%=Timeout%
  270.     Badblock!=True
  271.     Goto Booboo
  272.   Endif
  273.   '
  274.   If Char%<>Soh% And Char%<>Stx% And Char%<>Eot% ! wrong char (sync error)
  275.     Print "Sync error"
  276.     Badblock!=True
  277.     Goto Booboo
  278.   Endif
  279.   '
  280.   S%=Bsize%
  281.   If Char%=Soh% ! SOH means set block size to 128 bytes  (Xmodem)
  282.     Bsize%=128
  283.   Endif
  284.   If Char%=Stx% ! STX means set block size to 1024 bytes (Ymodem)
  285.     Bsize%=1024
  286.   Endif
  287.   '
  288.   Bput #1,Varptr(Ymbuf$),S% ! save after each block (slow, but it works)
  289.   '
  290.   If Char%=Eot%  ! at end of transfer, close file, and quit
  291.     Close #1
  292.     Out 1,Ack%   ! don't forget to ACK the EOT
  293.     '
  294.     ' Patch goto till I support Ymodem Batch
  295.     ' otherwise, I'd return to the beginning and get another block 0
  296.     ' (Goto Nxtfile)
  297.     '
  298.     Goto Ymrrtn
  299.     Goto Nxtfile
  300.   Endif
  301.   Inc Block%
  302.   Goto Startblock
  303.   '
  304.   Booboo:
  305.   '
  306.   @Purge          ! clear out RS-232 buffer
  307.   Out 1,Nak%      ! send NAK
  308.   Inc Ercnt%      ! increment error count
  309.   If Ercnt%=11
  310.     Print "Too many errors...aborting download!"
  311.     Out Rs232%,Can%
  312.     Out Rs232%,Can%
  313.     Close #1
  314.     Goto Ymrrtn
  315.   Endif
  316.   Goto Awaitsoh   ! wait for SOH/STX of retry
  317.   '
  318.   Check_sum:
  319.   '
  320.   Cksum%=Cksum% And 255  ! only 8 bits of the checksum are used
  321.   If Cksum%<>Icksum%
  322.     Print "Checksum error"
  323.     Goto Booboo
  324.   Endif
  325.   Goto Block_ok
  326.   '
  327.   Ymrrtn:
  328. Return
  329.